<?php 

/* amazon product advertising client */
class amazon{
	/* this is a black list for book publishers to
	 * prevent amazon spam from hitting this site 
	 * with adverts for waste-bin books */
	public $blacklist = array("Books LLC", "Books Group", 
				"General Books LLC", "General Books Club",
				"Million-books.com", "Rare Books Club", 
				"Livres Groupe", "Bücher Gruppe", 
				"Betascript Publishing",  "Alphascript Publishing",
				"Vdm Verlag Dr. Mller Ag & Co. Kg");
	
	// region code identifying the region
	// the queries will be created for
	private $regionCode = "de";
	
	/* checks the language code and sets the */
	public function __construct($languageCode){
		if($languageCode=="en-GB"){
			$this->regionCode = "co.uk";
		}if($languageCode=="de-DE"){
			$this->regionCode = "de";
		}
	}
	
	/* filters blacklisted publisher books from a 
	 * list of book results from the amazon paapi */
	public function filter($list){
		$result = $list;
		
		/* this walks through all items in the results checking 
		 * if the publisher is in the local publisher blacklist 
		 * and then unsets the book element in the index */
		for($i=0;$i<count($result->Items->Item);$i++){
			for($b=0;$b<count($this->blacklist);$b++){
				$book_publisher = strtolower($result->Items->Item[$i]->ItemAttributes->Publisher);
				$blacklist_publisher = strtolower($this->blacklist[$b]);
				
				if($book_publisher==$blacklist_publisher){
					// drop the item by setting it to null
					$result->Items->Item[$i] = null;
				}
			}
			
			// also drop it when no price information was provided,
			// no author exists or no image is available for this publication
			if(property_exists($result->Items->Item[$i], "OfferSummary")==false
				||property_exists($result->Items->Item[$i]->ItemAttributes, "Author")==false
				||property_exists($result->Items->Item[$i], "MediumImage")==false){
				// again drop it by setting to null
				$result->Items->Item[$i] = null;
			}
		}
		
		// a little tricky now to remove the null element
		$result = simplexml_load_string(str_replace
			("<Item></Item>", "", $result->asXML()));
			
		return $result;
	}
	
	/* does the same as 'itemSearch', but uses caching to 
	 * improve the overall page load time. It is highly 
	 * recommend to only use this function instead of 
	 * itemSearch directly as especially the Amazon 
	 * Product Advertising API is pretty slow */
	public function itemSearchCached($keywords,$searchIndex,$forceRefresh = false){
		$result = array();
		$c = new cache();
		$cache_key = $c->hash("amznpaapi.".$this->regionCode.$keywords.$searchIndex);
		if($c->has($cache_key)==true && $forceRefresh==false){
			// output from cache when present and 
			// refresh is not forced
			$result = simplexml_load_string($c->get($cache_key));
		}else{
			// if not in cache, load it and cache it
			$result = $this->itemSearch($keywords, $searchIndex);
			// finally drop it into the cache for one day
			$c->put($cache_key, $result->asXml(), (time()+86400));
		}
		
		return $result;
	}
	
	/*
	Searches an item with the Amazon ECommerce Service
	
	Param 'Keywords': Keyword to search with
	Param 'SearchIndex':
		The index to search in.
		
		Availables values are:
		Apparel,Automotive,Books,DVD,Electronics,
		GourmetFood,Kitchen,Music,PCHardware,PetSupplies,
	    Software,SoftwareVideoGames,SportingGoods,
		Tools,Toys,VHS,VideoGames 
		
		The value 'Blended' will search in all of them.
	
	*/
	public function itemSearch($keywords,$searchIndex){
		$result = $this->signedRequest(array(
						'Operation'=>'ItemSearch',
						'SearchIndex'=> $searchIndex,
						'ResponseGroup'=> 'Medium',
						'Keywords'=> $keywords
					));

		// filter blacklisted items
		$result = $this->filter($result);
		
		return $result;
	}
	
	private function signedRequest($params)
	{
		/*
		Copyright (c) 2009 Ulrich Mierendorff
	 
		Permission is hereby granted, free of charge, to any person obtaining a
		copy of this software and associated documentation files (the "Software"),
		to deal in the Software without restriction, including without limitation
		the rights to use, copy, modify, merge, publish, distribute, sublicense,
		and/or sell copies of the Software, and to permit persons to whom the
		Software is furnished to do so, subject to the following conditions:
	 
		The above copyright notice and this permission notice shall be included in
		all copies or substantial portions of the Software.
	 
		THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
		IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
		FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
		THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
		LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
		FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
		DEALINGS IN THE SOFTWARE.
		*/
	 
		/*
		Parameters:
			$region - the Amazon(r) region (ca,com,co.uk,de,fr,jp)
			$params - an array of parameters, eg. array("Operation"=>"ItemLookup",
							"ItemId"=>"B000X9FLKM", "ResponseGroup"=>"Small")
			$public_key - your "Access Key ID"
			$private_key - your "Secret Access Key"
		*/
	 
		$public_key = CONFIG_AMAZON_PUBLIC_KEY;
		$private_key = CONFIG_AMAZON_PRIVATE_KEY;
		$associateTag = CONFIG_AMAZON_ASSOCIATE_TAG;
	 
		// some paramters
		$method = "GET";
		$host = "ecs.amazonaws.".$this->regionCode;
		$uri = "/onca/xml";
	 
		// additional parameters
		$params["Service"] = "AWSECommerceService";
		$params["AWSAccessKeyId"] = $public_key;
		$params["AssociateTag"] = $associateTag;
		// GMT timestamp
		$params["Timestamp"] = gmdate("Y-m-d\TH:i:s\Z");
		// API version
		$params["Version"] = "2009-03-31";
	 
		// sort the parameters
		ksort($params);
	 
		// create the canonicalized query
		$canonicalized_query = array();
		foreach ($params as $param=>$value)
		{
			$param = str_replace("%7E", "~", rawurlencode($param));
			$value = str_replace("%7E", "~", rawurlencode($value));
			$canonicalized_query[] = $param."=".$value;
		}
		$canonicalized_query = implode("&", $canonicalized_query);
	 
		// create the string to sign
		$string_to_sign = $method."\n".$host."\n".$uri."\n".$canonicalized_query;
	 
		// calculate HMAC with SHA256 and base64-encoding
		$signature = base64_encode(hash_hmac("sha256", $string_to_sign, $private_key, True));
	 
		// encode the signature for the request
		$signature = str_replace("%7E", "~", rawurlencode($signature));
	 
		// create request
		$request = "http://".$host.$uri."?".$canonicalized_query."&Signature=".$signature;
	 
		// do request
		$response = @file_get_contents($request);
	 
		if ($response === False)
		{
			return False;
		}
		else
		{
			// parse XML
			$pxml = simplexml_load_string($response);
			if ($pxml === False)
			{
				return False; // no xml
			}
			else
			{
				return $pxml;
			}
		}
	}
}
?>